using System;
using System.Collections.Generic;

namespace Conusic
{
    public static class SongChooser
    {
        /// <summary>
        /// AudioRecord in accepted, if length of it in (duration-modeDelta; duration+modeDelta)
        /// </summary>
        private const int ModeDelta = 5;

        /// <summary>
        /// Find mode(most frequent value) in integer list.
        /// </summary>
        /// <param name="list">List of integers.</param>
        /// <returns>Mode value. </returns>
        private static int FindMode(List<int> list)
        {
            list.Sort();
            int previus = list[0];
            int currentCount = 0;
            int mode = list[0];
            int maxCount = 0;
            foreach (var i in list)
            {
                if (i == previus)
                {
                    currentCount++;
                }
                else
                {
                    if (currentCount > maxCount)
                    {
                        maxCount = currentCount;
                        mode = previus;
                    }
                    currentCount = 1;
                }
                previus = i;
            }
            return mode;
        }

        /// <summary>
        /// Execute on SearchAudioAsync command callback.
        /// </summary>
        /// <param name="listAudio">List of audio records.</param>
        /// <param name="searchedString">Search request on Vkontakte.ru.</param>
        /// <param name="preferedBitrate">Found bitrate greater them it. </param>
        /// <param name="audioRecordCountForBitrateFind">Count of audio record which check for find bitrate. </param>
        /// <returns>Selected audiorecord in list. </returns>
        public static AudioRecord OptimizeFindRecordInList(List<AudioRecord> listAudio, string searchedString, int preferedBitrate , int audioRecordCountForBitrateFind )
        {
            var comparerOnlyChars = new StringComparerOnlyChars();
            AudioRecord foundRecord = null;

            // Create new list with condidional elements (o(n))
            List<AudioRecord> audioRecordsCorrectName = listAudio.FindAll(
                ar => comparerOnlyChars.Equals(ar.ArtistAndComposition, searchedString)
                );

            List<int> lengthList = new List<int>(listAudio.Count);
            foreach (AudioRecord record in audioRecordsCorrectName)
            {
                lengthList.Add(record.Duration);
            }

            // if nothing found
            if (audioRecordsCorrectName.Count == 0)
                return null;

            // if only one song found
            if (audioRecordsCorrectName.Count == 1)
                return audioRecordsCorrectName[0];

            // Sort Length list for find mode(statistics) (o(n^2+n))
            int mode = FindMode(lengthList);

            int maxBitrate = 0;
            int i = 0;
            int requestedProcced = 0;
            while (i < audioRecordsCorrectName.Count && requestedProcced < audioRecordCountForBitrateFind && maxBitrate < preferedBitrate)
            {
                if (Math.Abs(audioRecordsCorrectName[i].Duration - mode) < ModeDelta)
                {
                    int bitrate = VkontakteAudio.GetAverageBitrate(audioRecordsCorrectName[i]);
                    requestedProcced++;
                    if (bitrate > maxBitrate)
                    {
                        foundRecord = audioRecordsCorrectName[i];
                        maxBitrate = bitrate;
                    }
                }
                i++;
            }

            return foundRecord;
        }
    }
}